package com.hexinfo.dmpro.monitor.service.serviceparam;

import cn.hutool.core.util.StrUtil;
import com.hexinfo.dmpro.monitor.dao.ClusterHostDao;
import com.hexinfo.dmpro.monitor.dao.ImpalaAppDao;
import com.hexinfo.dmpro.monitor.dao.MonitorDao;
import com.hexinfo.dmpro.monitor.dao.serviceparam.CmTargetParamDao;
import com.hexinfo.dmpro.monitor.model.ClusterHostModel;
import com.hexinfo.dmpro.monitor.model.base.MonitorReq;
import com.hexinfo.dmpro.monitor.model.serviceparam.CmTargetModel;
import com.hexinfo.dmpro.monitor.service.CmStateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CmTargetParamHandlerService {

    @Autowired
    private MonitorDao monitorDao;

    @Autowired
    private CmStateService cmStateService;

    @Autowired
    private CmTargetParamDao cmTargetParamDao;

    @Autowired
    private ClusterHostDao clusterHostDao;

    @Autowired
    private ImpalaAppDao impalaAppDao;

    // 获取CM服务监控
    public Map<String, String> getCmServiceStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> serviceMap = cmStateService.seleveryDayInspect();
        // for循环遍历serviceStrMap,若对应的value为空字符串,设置该vule值为"CM服务监控：正常"+"\n"
        Map<String, String> serviceStrMap = new HashMap<>();
        for (String cmName : cmNameInfoMap.keySet()) {
            if (serviceMap.containsKey(cmName)) {
                serviceStrMap.put(cmName, StrUtil.equals(serviceMap.get(cmName), "") ? "CM服务监控：正常" : serviceMap.get(cmName));
            } else {
                serviceStrMap.put(cmName, "CM服务监控：正常"+"\n");
            }
        }
        return serviceStrMap;
    }

    // zookeeper连接数监控
    public Map<String, String> getZookeeperStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> zookeeperStrMap = new HashMap<>();
        List<CmTargetModel> zookeeperList = cmTargetParamDao.selZookeeperConn();
        Map<String, String> zookeeperMap = zookeeperList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (zookeeperMap.containsKey(cmName)){
                zookeeperStrMap.put(cmName,zookeeperMap.get(cmName)+"\n");
            } else {
                zookeeperStrMap.put(cmName,"暂无数据"+"\n");
            }
        }
        return zookeeperStrMap;
    }

    // impala每个主机监控:每个主机jvm近30分最大
    public Map<String, String> getImpalaStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> impalaStrMap = new HashMap<>();
        List<CmTargetModel> impalaList = cmTargetParamDao.selImpalaHostsJvmMax();
        Map<String, String> impalaMap = impalaList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (impalaMap.containsKey(cmName)) {
                String format = unitConversions(impalaMap.get(cmName), "B");
                impalaStrMap.put(cmName, format+"\n");
            } else {
                impalaStrMap.put(cmName, "暂无数据"+"\n");
            }
        }
        return impalaStrMap;
    }

    // HDFS使用容量
    public Map<String, Map<String, String>> getHdfsStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, Map<String, String>> hdfsCapacityUsedStrMap = new HashMap<>();
        List<CmTargetModel> hdfsCapacityUsedList = cmTargetParamDao.hdfsCapacityUsed();
        Map<String, CmTargetModel> hdfsMap = hdfsCapacityUsedList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, cmTargetModel -> cmTargetModel));
        for (String cmName : cmNameInfoMap.keySet()) {
            Map<String, String> cmNameMap = new HashMap<>();
            if (hdfsMap.containsKey(cmName)) {
                String format = unitConversions(hdfsMap.get(cmName).getTargetValue(), "B");
                cmNameMap.put("useValue", format);
                cmNameMap.put("proportion",hdfsMap.get(cmName).getProportionHdfs());
            } else {
                cmNameMap.put("useValue", "暂无数据");
                cmNameMap.put("proportion","暂无数据");
            }
            hdfsCapacityUsedStrMap.put(cmName,cmNameMap);
        }
        return hdfsCapacityUsedStrMap;
    }

    // hive的连接数
    public Map<String, String> getHiveConnsStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hiveConnsStrMap = new HashMap<>();
        List<CmTargetModel> hiveConnsList = cmTargetParamDao.selHiveConn();
        Map<String, CmTargetModel> hiveConnsMap = hiveConnsList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, cmTargetModel -> cmTargetModel));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hiveConnsMap.containsKey(cmName)){
                hiveConnsStrMap.put(cmName,hiveConnsMap.get(cmName).getRoleType()+"连接数: "+hiveConnsMap.get(cmName).getTargetValue()+"\n");
            } else {
                hiveConnsStrMap.put(cmName, "暂无数据"+"\n");
            }
        }
        return hiveConnsStrMap;
    }

    // impala的连接数
    public Map<String, String> getImpalaConnsStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> impalaConnsStrMap = new HashMap<>();
        List<CmTargetModel> impalaConnsList = cmTargetParamDao.selImpalaConn();
        Map<String, String> impalaConnsMap = impalaConnsList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (impalaConnsMap.containsKey(cmName)){
                impalaConnsStrMap.put(cmName,"连接数: "+impalaConnsMap.get(cmName)+"\n");
            } else {
                impalaConnsStrMap.put(cmName, "暂无数据"+"\n");
            }
        }
        return impalaConnsStrMap;
    }

    // Hive metastore JVM使用状态
    public Map<String, String> getHiveMetastoreStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hiveMetastoreStrMap = new HashMap<>();
        List<CmTargetModel> hiveMetastoreList = cmTargetParamDao.selHiveMetastoreJvmMax();
        Map<String, String> hiveMetastoreMap = hiveMetastoreList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hiveMetastoreMap.containsKey(cmName)) {
                String format = unitConversions(hiveMetastoreMap.get(cmName), "B");
                hiveMetastoreStrMap.put(cmName, format);
            } else {
                hiveMetastoreStrMap.put(cmName, "暂无数据\n");
            }
        }
        return hiveMetastoreStrMap;
    }

    // Hive server2 JVM使用状态
    public Map<String, String> getHiveServer2StrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hiveServer2StrMap = new HashMap<>();
        List<CmTargetModel> hiveServer2List = cmTargetParamDao.selHiveServer2JvmMax();
        Map<String, String> hiveServer2Map = hiveServer2List.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hiveServer2Map.containsKey(cmName)) {
                String format = unitConversions(hiveServer2Map.get(cmName), "B");
                hiveServer2StrMap.put(cmName, format+"\n");
            } else {
                hiveServer2StrMap.put(cmName, "暂无数据\n");
            }
        }
        return hiveServer2StrMap;
    }

    // HBase RegionServer GC回收时间峰值
    public Map<String, String> getHbaseRegionServerStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hbaseRegionServerStrMap = new HashMap<>();
        List<CmTargetModel> hbaseRegionServerList = cmTargetParamDao.selHbaseRegionServerGcMaxTime();
        Map<String, String> hbaseRegionServerMap = hbaseRegionServerList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hbaseRegionServerMap.containsKey(cmName)) {
                hbaseRegionServerStrMap.put(cmName, hbaseRegionServerMap.get(cmName)+"ms\n");
            } else {
                hbaseRegionServerStrMap.put(cmName, "暂无数据");
            }
        }
        return hbaseRegionServerStrMap;
    }

    // HBase Master JVM使用状态
    public Map<String, String> getHbaseMasterJvmStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hbaseMasterJvmStrMap = new HashMap<>();
        List<CmTargetModel> hbaseMasterJvmList = cmTargetParamDao.selHbaseMasterJvmMax();
        Map<String, String> hbaseMasterJvmMap = hbaseMasterJvmList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hbaseMasterJvmMap.containsKey(cmName)) {
                String format = unitConversions(hbaseMasterJvmMap.get(cmName), "MB");
                hbaseMasterJvmStrMap.put(cmName, format);
            } else {
                hbaseMasterJvmStrMap.put(cmName, "暂无数据");
            }
        }
        return hbaseMasterJvmStrMap;
    }

    // HBase RegionServer JVM使用状态
    public Map<String, String> getHbaseRegionServerJvmStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hbaseRegionServerJvmStrMap = new HashMap<>();
        List<CmTargetModel> hbaseRegionServerJvmList = cmTargetParamDao.selHbaseRegionServerJvmMax();
        Map<String, String> hbaseRegionServerJvmMap = hbaseRegionServerJvmList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hbaseRegionServerJvmMap.containsKey(cmName)) {
                String format = unitConversions(hbaseRegionServerJvmMap.get(cmName), "MB");
                hbaseRegionServerJvmStrMap.put(cmName, format+"\n");
            } else {
                hbaseRegionServerJvmStrMap.put(cmName, "暂无数据\n");
            }
        }
        return hbaseRegionServerJvmStrMap;
    }

    // Zookeeper JVM使用状态
    public Map<String, String> getZookeeperJvmStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> zookeeperJvmStrMap = new HashMap<>();
        List<CmTargetModel> zookeeperJvmList = cmTargetParamDao.selZookeeperJvmMax();
        Map<String, String> zookeeperJvmMap = zookeeperJvmList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (zookeeperJvmMap.containsKey(cmName)) {
                String format = unitConversions(zookeeperJvmMap.get(cmName), "MB");
                zookeeperJvmStrMap.put(cmName, format+"\n");
            } else {
                zookeeperJvmStrMap.put(cmName, "暂无数据\n");
            }
        }
        return zookeeperJvmStrMap;
    }

    // 主机状态
    public Map<String, String> getHostsHealthSummaryStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hostsHealthSummaryStrMap = new HashMap<>();
        List<ClusterHostModel> clusterHostModelList = clusterHostDao.queryHostInfo(new ClusterHostModel());
        Map<String, List<ClusterHostModel>> hostsHealthSummaryMap = clusterHostModelList.stream().collect(Collectors.groupingBy(ClusterHostModel::getCmName));
        for (String cmName : cmNameInfoMap.keySet()) {
            String errHostMessage = "";
            if (hostsHealthSummaryMap.containsKey(cmName)) {
                // 获取存在异常的服务器
                List<ClusterHostModel> clusterHostModel = hostsHealthSummaryMap.get(cmName).stream().filter(s -> !"GOOD".equals(s.getHealthSummary())).collect(Collectors.toList());
                for (ClusterHostModel clusterInfo : clusterHostModel) {
                    errHostMessage += StrUtil.format("\n主机【{}】(ip: {})状态异常：{}", clusterInfo.getHostName(), clusterInfo.getIp(), clusterInfo.getHealthSummary());
                }
            }
            hostsHealthSummaryStrMap.put(cmName, StrUtil.isBlank(errHostMessage) ? "正常" : errHostMessage);
        }
        return hostsHealthSummaryStrMap;
    }

    //万国集群监控大屏 impala和yarn失败任务监控
    public Map<String, String> getImpalaYarnStrFailStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hostsHealthSummaryStrMap = new HashMap<>();
        for (String cmName : cmNameInfoMap.keySet()) {
            String impalaFileNum = impalaAppDao.selectImpalaExecFailNum(cmName);
            String yarnFileNum = impalaAppDao.selectYarnExecFailNum(cmName);
            hostsHealthSummaryStrMap.put(cmName, "impala失败任务数："+impalaFileNum+", "+"yarn失败任务数："+yarnFileNum+"\n");
        }
        return hostsHealthSummaryStrMap;
    }

    // hdfs丢失块监控
    public Map<String, String> getHdfsLossBlockStrMap(Map<String, MonitorReq> cmNameInfoMap) {
        Map<String, String> hdfsLossBlockStrMap = new HashMap<>();
        List<CmTargetModel> hdfsLossBlockList = cmTargetParamDao.hdfsLossBlock();
        Map<String, String> hdfsLossBlockMap = hdfsLossBlockList.stream().collect(Collectors.toMap(CmTargetModel::getCmName, CmTargetModel::getTargetValue));
        for (String cmName : cmNameInfoMap.keySet()) {
            if (hdfsLossBlockMap.containsKey(cmName)) {
                hdfsLossBlockStrMap.put(cmName, StrUtil.equals(hdfsLossBlockMap.get(cmName), "0") ? "无异常\n" : hdfsLossBlockMap.get(cmName) + "\n");
            } else {
                hdfsLossBlockStrMap.put(cmName, "暂无数据\n");
            }
        }
        return hdfsLossBlockStrMap;
    }

    // 单位转换
    private String unitConversions(String valueInfo, String unit) {
        double value = Double.parseDouble(valueInfo);
        String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
        int index = Arrays.asList(units).indexOf(unit);
        while (value >= 1024 && index < units.length - 1) {
            value /= 1024;
            index++;
        }
        return String.format("%.1f", value) + units[index];
    }
}
